package com.guosen.zebra.gateway.servlet;

import com.alibaba.fastjson.JSONObject;
import com.guosen.zebra.gateway.exception.RouteNotFound;
import com.guosen.zebra.gateway.exception.ServiceNotFound;
import com.guosen.zebra.gateway.handler.ZebraServiceHandler;
import com.guosen.zebra.gateway.util.Constants;
import com.guosen.zebra.gateway.util.HttpRequestUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * Zebra服务网关servlet，通过此servlet暴露对外接口
 */
@WebServlet(urlPatterns = Constants.GATE_WAY_URI_PREFIX + "/*", loadOnStartup = 1)
@Component
public class ZebraServiceApiServlet extends HttpServlet {

    private static final String CONTENT_TYPE = "application/json; charset=utf-8";

    @Autowired
    private ZebraServiceHandler zebraServiceHandler;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        service(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        service(req, resp);
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String originalRequestURI = req.getRequestURI();

        // 去掉前缀，以便后续进行匹配
        String requestURI = StringUtils.substringAfter(originalRequestURI, Constants.GATE_WAY_URI_PREFIX);
        JSONObject requestParameters = HttpRequestUtil.getJSONParam(req);
        Map<String, String> headers = HttpRequestUtil.getHeader(req);

        JSONObject result = null;
        String errorMessage = null;
        try {
            result = zebraServiceHandler.handleRequest(requestURI, requestParameters, headers);
        } catch (RouteNotFound routeNotFound) {
            errorMessage = "Route not found of URI : " + originalRequestURI;
        } catch (ServiceNotFound serviceNotFound) {
            errorMessage = "Service not found of URI : " + originalRequestURI;
        }

        if (result == null) {
            writeNotFound(resp, errorMessage);
        }
        else {
            writeJson(resp, result);
        }
    }

    private void writeJson(HttpServletResponse response, JSONObject responseBody) throws IOException {
        response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
        response.setContentType(CONTENT_TYPE);

        try (ServletOutputStream servletOutputStream = response.getOutputStream()) {
            servletOutputStream.write(responseBody.toJSONString().getBytes(StandardCharsets.UTF_8));
        }
    }

    private void writeNotFound(HttpServletResponse resp, String msg) throws IOException {
        resp.sendError(HttpServletResponse.SC_NOT_FOUND, msg);
    }
}
